# -*- coding: utf-8 -*-

from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.core.audio import SoundLoader
from kivy.properties import NumericProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import *
from constants import FAILED_SOUND, GUESSED_SOUND,\
    LAST_SECONDS_FINISHED_SOUND, PUT_BACK_SOUND, TIME_UP_SOUND,\
    PATH

import model.gamestate
from model.gamestate import WordGuessResult
from ui.hat_widget import HatWidget

"""
It neeeds Gamestate with Settings.time_per_round_sec, Settings.time_left_sec
and Hat with methods Hat.add_word(), Hat.get_word()
It changes GameState.Game.game_round.current_word,
GameState.game_round.words
It can change phase from GUESS_WORD to RESULTS_OF_ONE_PAIR
It stores current word in gamestate.game_round.current_word
    if resulf isnt known
"""

DISABLE_TIME_SEC = 0.4
RELEASE_TIME = 1


class Picture(Image):
    pass


class GuessWordScreen(HatWidget):
    pbValue = NumericProperty()
    pbMaxValue = NumericProperty()
    skip_words_left = NumericProperty()
    word_str = StringProperty()
    path_to_pict = StringProperty()

    def __init__(self, gamestate, presenter, **kwargs):
        """
        It's constructor of GuessWordScreen
        Args:
            gamestate: (GameState)
            presenter: (Presenter)
        """
        super(GuessWordScreen, self).__init__(**kwargs)
        self.path_to_pict = PATH + '/assets/word-background.jpg'
        self.release_time = 0
        self.left_pressed = False
        self.right_pressed = False
        self.gamestate = gamestate
        self.presenter = presenter
        self.gamestate.shall_change = True
        self.sound = SoundLoader.load(
            self.presenter.settings.sound.sound_failed)
        if self.gamestate.is_pressed_pause is False:
            self.gamestate.game_round.words = []
        else:
            self.gamestate.is_pressed_pause = False
        if presenter.settings.game.may_pause_game is False:
            self.pause_button.enabled = False
        if not presenter.settings.game.is_progress_bar:
            """
            remove progressbar
            """
            self.box_layout_1.remove_widget(self.progress_bar)
            self.box_layout_1.size_hint_x = 0.2

        self.get_word()
        self.is_last_second = False

        self.pbMaxValue = self.gamestate.settings.time_per_round_sec
        self.pbValue = self.pbMaxValue - \
            self.gamestate.game_round.time_left_sec

        if self.gamestate.game_round.time_left_sec > 0:
            Clock.schedule_interval(self.update_state, 0.02)
            self.is_time_out = False
        else:
            self.is_time_out = True
            self.word_label.color = 0.4, 0.4, 0.4, 1
            self.pause_button.enabled = False

        self.skip_words_left = self.presenter.settings.game.skip_words
        self.redraw_skip_button()
        if not self.presenter.settings.game.show_tournament_buttons:
            self.left_btn.width = 0
            self.bx_layout.remove_widget(self.left_btn)
            self.bx_layout.remove_widget(self.right_btn)
        else:
            Clock.schedule_interval(self.pick_sound, 2)

    def enable_guess_button(self, dt):
        """
        It can disable guess button for 0.2 seconds.
        """
        self.guess_button.enabled = True

    def go_to_next(self):
        """
        It can change phase from GUESS_WORD to RESULTS_OF_ONE_PAIR
        """
        if not self.is_time_out:
            Clock.unschedule(self.update_state)
        Clock.unschedule(self.pick_sound)
        Clock.unschedule(self.enable_guess_button)
        Clock.unschedule(self.last_seconds_finished)
        self.presenter.change_phase(model.gamestate.Phase.RESULTS_OF_ONE_PAIR)

    def add_current_word(self, result):
        """
        It can add current word to GameState.game_round.words.
        Args:
            result: WordGuessResult
        """
        word = WordGuessResult(
            self.gamestate.game_round.current_word,
            result, self.gamestate.
            settings.time_per_round_sec
            - self.gamestate.game_round.time_left_sec)
        self.gamestate.game_round.words.append(word)

    def hat_is_empty(self):
        """
        This method checks that hat is empty
        """
        return len(self.gamestate.hat.words) == 0

    def get_word(self):
        """
        This method can get word from hat and draw it on the screen.
        It changes gamestate.game_round.current_word
        """
        if self.gamestate.game_round.current_word is None:
            self.gamestate.game_round.current_word =\
                self.gamestate.hat.next_word()
        self.word_str = self.gamestate.game_round.current_word.text

    def update_state(self, dt):
        """
        This function is responsible for updating progress bat,
        and playing "beep sounds" and vibration.
        Also it can change buttons text:
        1) skip_button from "end_round" to "not_guessed"
        It can disable pause button in last seconds
        Args:
            dt: (float) - delta t
        """
        self.pbValue += dt
        if self.gamestate.game_round is not None:
            self.gamestate.game_round.time_left_sec = self.pbMaxValue - \
                self.pbValue
        if ((self.pbValue >= self.pbMaxValue - 1) and
                (not self.is_last_second)):
            if self.presenter.settings.sound.sound_on:
                long_sound = SoundLoader.load(TIME_UP_SOUND)
                long_sound.play()
            self.is_last_second = True
        if ((self.pbValue >= self.pbMaxValue) and
                (not self.is_time_out)):
            self.presenter.adapter.vibrate()
            Clock.schedule_once(self.last_seconds_finished,
                                self.gamestate.settings.time_before_out_sec)
            self.pause_button.enabled = False
            self.skip_button.text = _('Not guessed')
            self.is_time_out = True
            self.word_label.color = 1, 0.4, 0.4, 1
            self.redraw_skip_button()
            Clock.unschedule(self.update_state)

    def pick_sound(self, dt):
        """
        This function updates tournament_buttons timer.
        If player do not touch this buttons for RELEASE_TIME sec
        starts terrible sound
        Args:
            dt: (float) - delta t
        """
        self.release_time += dt
        if self.release_time >= RELEASE_TIME and \
           not(self.left_pressed and self.right_pressed) and \
           self.gamestate.game_round.time_left_sec > 0:
            self.sound.play()

    def button_released(self, pos):
        """
        This method will be called when tournament_buttons ara released.
        It equates release_time timer to 0
        Args:
            pos: (int) pos = 0, if left button released. 1 if right button.
        """
        if self.left_pressed and self.right_pressed:
            self.release_time = 0
        if pos == 0:
            self.left_pressed = False
        else:
            self.right_pressed = False

    def button_pressed(self, pos):
        """
        This method will be called when tournament_buttons ara pressed.
        It equates release_time timer to 0
        Args:
            pos: (int) pos = 0, if left button pressed. 1 if right button.
        """
        if self.left_pressed and self.right_pressed:
            self.release_time = 0
        if pos == 0:
            self.left_pressed = True
        else:
            self.right_pressed = True

    def last_seconds_finished(self, dt):
        """
        This function is responsible for last three seconds ending.
        It can play sound and vibrate.
        It changes word label color and skip_button text
        Args:
            dt: (float) - delta t
        """
        if self.presenter.settings.sound.sound_on:
            long_sound = SoundLoader.load(LAST_SECONDS_FINISHED_SOUND)
            long_sound.play()
        self.presenter.adapter.vibrate()
        self.word_label.color = 0.07, 0.07, 0.07, 1
        self.redraw_skip_button()

    def hat_is_empty(self):
        """
        This method checks that hat is empty
        """
        return len(self.gamestate.hat.words) == 0

    def guessed(self):
        """
        This method add current word to curr_round.words, with GUESS flag.
        If Hat is not empty, then this word will be update_stated, else method
        GoToNext can change current game phase to RESULTS_OF_ONE_PAIR
        """
        if (self.presenter.settings.sound.sound_on) and \
           (self.presenter.settings.sound.sound_guessed != 'No sound'):
            sound = SoundLoader.load(
                self.presenter.settings.sound.sound_guessed)
            sound.play()
        self.button_timer_stoped = True
        self.add_current_word(WordGuessResult.GUESS)
        self.gamestate.game_round.current_word = None
        if not (self.hat_is_empty() or self.is_time_out):
            self.guess_button.enabled = False
            Clock.schedule_once(self.enable_guess_button,
                                DISABLE_TIME_SEC)
            self.get_word()
        else:
            self.go_to_next()

    def fail(self):
        """
        This method add current word to curr_round.words, with FAIL flag and
        change game Phase to RESULTS_OF_ONE_PAIR game phase
        """
        if (self.presenter.settings.sound.sound_on) and \
           (self.presenter.settings.sound.sound_failed != 'No sound'):
            sound = SoundLoader.load(
                self.presenter.settings.sound.sound_failed)
            sound.play()
        self.add_current_word(WordGuessResult.FAIL)
        self.gamestate.game_round.current_word = None
        self.go_to_next()

    def put_back(self):
        """
        This method add current word to curr_round.words, with PUT_BACK flag
        and add current word into the hat.
        """
        if (self.presenter.settings.sound.sound_on) and \
           (self.presenter.settings.sound.sound_put_back != 'No sound'):
            sound = SoundLoader.load(
                self.presenter.settings.sound.sound_put_back)
            sound.play()
        if self.is_time_out or self.skip_words_left <= 0:
            self.add_current_word(WordGuessResult.TIME_OUT)
            self.go_to_next()
        elif self.skip_words_left != 0:
            self.add_current_word(WordGuessResult.PUT_BACK)
            self.gamestate.hat.add_word(self.gamestate.game_round.current_word)
            self.gamestate.game_round.current_word = None
            self.get_word()

            if self.skip_words_left < 2:
                self.skip_words_left -= 1
                self.redraw_skip_button()

    def redraw_skip_button(self):
        """
        Skip button can change its text. This method do it.
        its normal text: "End round"
        if time is out then its text is "Not Guessed"
        """
        if self.is_time_out:
            self.skip_button.text_normal = _('Not guessed')
            self.skip_button.is_normal_button = True
        elif self.skip_words_left > 0:
            self.skip_button.text_normal = _('Change')
            self.skip_button.is_normal_button = True
        else:
            self.skip_button.text_normal = _('End round')
            self.skip_button.is_normal_button = False

    def paused(self):
        """
        This method called when pause_button is pressed.
        It must stop progress bar, last_seconds timer,
        tournament buttons sound
        It can change phase to FROM_TO phase
        """
        if not self.is_time_out:
            Clock.unschedule(self.update_state)
        Clock.unschedule(self.enable_guess_button)
        Clock.unschedule(self.last_seconds_finished)
        Clock.unschedule(self.pick_sound)
        self.gamestate.shall_change = False
        self.gamestate.is_pressed_pause = True
        self.presenter.change_phase(model.gamestate.Phase.FROM_TO)
